﻿//////////////////////////////////////////////////////////////////////
// <copyright file=Vector2D.cs">
//     Copyright (c) 2010
//     Released under  GNU GENERAL PUBLIC LICENSE
//     http://dev.perl.org/licenses/gpl1.html
// </copyright>
// <date> 3/25/2010 1:58:48 AM </date>
// <author> B. Endrovski </author>
// <web> http://furiouspixels.blogspot.com/ </web>
//////////////////////////////////////////////////////////////////////

using System;

namespace ContourReconstruction
{
	/// <summary>
	/// Lightweight vector class
	/// Use class instead of struct to enable references on vector objects
	/// as structs a value types
	/// </summary>
    public class Vector2D
    {		
		public float X { get; set; }

		public float Y { get; set; }

        public Vector2D(float x, float y)
        {
            X = x;
            Y = y;
        }

		public Vector2D(float val)
		{
			X = val;
			Y = val;
		}

        public void Zero()
        {
            X = 0.0f;
            Y = 0.0f;
        }

        public void Normalize()
        {
            float l = Length;
            X /= l;
            Y /= l;
        }

        public float Dot(Vector2D other)
        {
            return X * other.X + Y * other.Y;
        }

		public float Length
		{
			get { return (float)Math.Sqrt(X * X + Y * Y); }
		}

		public float LengthSq
		{
			get { return X * X + Y * Y; }
		}

        public float Distance(Vector2D other)
        {
            return (float)Math.Sqrt(DistanceSq(other));
        }

        public float DistanceSq(Vector2D other)
        {
			return (X - other.X) * (X - other.X) + (Y - other.Y) * (Y - other.Y);
        }

		public override int GetHashCode()
		{
			Vector2D origin = new Vector2D((float)Math.E, (float)Math.PI);							// Pick a weird coodrinate frame
			return X.GetHashCode() ^ Y.GetHashCode() ^ Distance(origin).GetHashCode();				// Looks like .NET uses the mantisa
		}

		public override bool Equals(object obj)
		{
			return (obj as Vector2D) == this;
		}

		public Vector2D Perp
		{
			get { return new Vector2D(-Y, X); }
		}

        public static bool operator ==(Vector2D v1, Vector2D v2) { return v2.X == v1.X && v2.Y == v1.Y; }

        public static bool operator !=(Vector2D v1, Vector2D v2) { return v2.X != v1.X || v2.Y != v1.Y; }

        public static Vector2D operator +(Vector2D v1, Vector2D v2)
        {
            return new Vector2D(v1.X + v2.X, v1.Y + v2.Y);
        }

        public static Vector2D operator -(Vector2D v1, Vector2D v2)
        {
            return new Vector2D(v1.X - v2.X, v1.Y - v2.Y);
        }

        public static Vector2D operator *(Vector2D v, float f)
        {
            return new Vector2D(v.X * f, v.Y * f);
        }

        public static Vector2D operator *(float f, Vector2D v)
        {
            return new Vector2D(v.X * f, v.Y * f);
        }

        public static Vector2D operator /(Vector2D v, float f)
        {
            return new Vector2D(v.X / f, v.Y / f);
        }

        public static Vector2D operator /(float f, Vector2D v)
        {
            return new Vector2D(v.X / f, v.Y / f);
        }

		public static Vector2D Normalize(Vector2D vec)
		{
			float l = vec.Length;
			return new Vector2D(vec.X / l, vec.Y / l);
		}		
    }
}
